/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package orgarqsindex;

import java.awt.Desktop;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import orgarqsindex.btree.BTreeGenerator;
import orgarqsindex.btree.BTreeNode;
import orgarqsindex.linkedlist.LinkedListGenerator;
import orgarqsindex.linkedlist.LinkedListValueNode;

/**
 *
 * @author Fernando Molon Toigo e Dyoni Bertuol
 */
public class ConsoleMenuView {

    private Scanner scanner;
    private FileExplorer fe;
    private RowModel rm;
    private File file;
    private BTreeNode bTreeRootNode;
    private LinkedListValueNode linkedListRootNode;
    private long hashIndexBlockSize;

    public ConsoleMenuView() {
        scanner = new Scanner(System.in);
        rm = new RowModel();
        file = new File("mainfile.txt");
        fe = new FileExplorer(file, rm.getRowSize());
    }

    public void showMainMenu() {

        boolean exit = false;

        while (!exit) {

            System.out.println("\nEscolha uma das opções abaixo:");
            System.out.println("0 - Sair");
            System.out.println("1 - Gerar arquivo");
            System.out.println("2 - Consultar");
            System.out.println("3 - Gerar índice de chave primária");
            System.out.println("4 - Gerar índice de árvore B");
            System.out.println("5 - Gerar índice hash por idade");

            System.out.print("Opção: ");
            int selectedOption = scanner.nextInt();

            switch (selectedOption) {
                case 0:
                    exit = true;
                    break;
                case 1:
                    generateRandomFile();
                    break;
                case 2:
                    showConsultMenu();
                    break;
                case 3:
                    generatePrimaryIndexFile();
                    break;
                case 4:
                    generateBTree();
                    break;
                case 5:
                    generateAgeHashIndexFile();
                    break;
            }

        }

        scanner.close();

    }

    private void generateRandomFile() {
        TestFileGenerator tfg = new TestFileGenerator();
        try {
            System.out.println("Gerando registros aleatórios e salvando...");
            if (tfg.generate("mainfile.txt")) {
                System.out.println("Arquivo de teste gerado com sucesso!");
                Desktop.getDesktop().open(new java.io.File("mainfile.txt"));
            } else {
                System.out.println("Ocorreu um erro ao gerar o arquivo de teste!");
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(OrgArqsIndex.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(OrgArqsIndex.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void generatePrimaryIndexFile() {
        
        PrimaryKeyIndexFileGenerator g = new PrimaryKeyIndexFileGenerator(file, new File("index.txt"), rm.getRowSize(), rm.getRgBeginIndex(), rm.getRgSize());
        try {
            g.generate();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }

    private void showConsultMenu() {
        System.out.println("\nDeseja consultar por:");
        System.out.println("0 - Voltar");
        System.out.println("1 - RG por exaustiva");
        System.out.println("2 - RG por índice primário");
        System.out.println("3 - RG por índice de árvore B");
        System.out.println("4 - Idade por índice hash");
        System.out.println("5 - Nome por exaustiva");
        System.out.println("6 - Nome por lista encadeada");
        System.out.println("7 - Endereço por exaustiva");
        System.out.print("Opção: ");
        int selectedOption = scanner.nextInt();

        switch (selectedOption) {
            case 1:
                searchByRGUsingFullScan();
                break;
            case 2:
                searchByRGUsingPrimaryKeyIndex();
                break;
            case 3:
                searchByRGUsingBTree();
                break;
            case 4:
                searchByAgeUsingHashIndex();
                break;
            case 5:
                searchByNameUsingFullScan();
                break;
            case 6:
                searchByNameUsingLinkedList();
                break;
            case 7:
                searchByAddressUsingFullScan();
                break;
        }
    }

    private void searchByRGUsingFullScan() {
        String rg = "";
        while (rg.length() != 10) {
            System.out.print("Informe o RG: ");
            rg = scanner.next();

            if (rg.length() != 10) {
                System.out.println("O RG deve possuir 10 dígitos!");
            }
        }
        try {
            System.out.println("Buscando registro com RG: " + rg + "...\n");
            List<RowModel> list = fe.exhaustiveScan(rm.getRgBeginIndex(), rm.getRgSize(), rg);

            if (list.isEmpty()) {
                System.out.println("Não encontrado!");
            } else {
                for (RowModel row : list) {
                    System.out.println(row.toString());
                }
            }

        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void searchByRGUsingBTree() {

        if (bTreeRootNode == null) {
            System.out.println("É necessário criar o ínice de Árvore B antes!");
            return;
        }

        String rg = "";
        while (rg.length() != 10) {
            System.out.print("Informe o RG: ");
            rg = scanner.next();

            if (rg.length() != 10)
                System.out.println("O RG deve possuir 10 dígitos!");
        }
        try {
            System.out.println("Buscando registro com RG: " + rg + "...\n");
            
            long searchParameter = Long.valueOf(rg);
            
            RowModel rowModel = fe.bTreeScan(bTreeRootNode, searchParameter);

            if (rowModel == null) {
                System.out.println("Não encontrado!");
            } else {
                System.out.println(rowModel.toString());
            }

        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void searchByNameUsingFullScan() {
        System.out.print("Informe o Nome: ");
        String name = scanner.next();
        try {
            System.out.println("Buscando registro de Nome: " + name + "...\n");
            List<RowModel> list = fe.exhaustiveScan(rm.getNameBeginIndex(), rm.getNameSize(), name);

            if (list.isEmpty()) {
                System.out.println("Não encontrado!");
            } else {
                for (RowModel row : list) {
                    System.out.println(row.toString());
                }
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void searchByAddressUsingFullScan() {
        System.out.print("Informe o Endereço: ");
        scanner.nextLine();
        String address = scanner.nextLine();
        try {
            System.out.println("Buscando registro de Endereço: " + address + "...\n");
            List<RowModel> list = fe.exhaustiveScan(rm.getAddressBeginIndex(), rm.getAddressSize(), address);

            if (list.isEmpty()) {
                System.out.println("Não encontrado!");
            } else {
                for (RowModel row : list) {
                    System.out.println(row.toString());
                }
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void searchByAgeUsingHashIndex() {
        int age = 0;
        System.out.print("Informe a idade: ");
        age = scanner.nextInt();

        try {
            System.out.println("Buscando registro com idade: " + age + "...\n");
            List<RowModel> list = fe.hashScan(new File("agehashindex.txt"), hashIndexBlockSize, age);

            if (list.isEmpty()) {
                System.out.println("Não encontrado!");
            } else {
                for (RowModel row : list) {
                    System.out.println(row.toString());
                }
            }

        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void searchByRGUsingPrimaryKeyIndex() {
        String rg = "";
        while (rg.length() != 10) {
            System.out.print("Informe o RG: ");
            rg = scanner.next();

            if (rg.length() != 10) {
                System.out.println("O RG deve possuir 10 dígitos!");
            }
        }
        try {
            System.out.println("Buscando registro com RG: " + rg + "...\n");
            List<RowModel> list = fe.indexScan(new File("index.txt"), rm.getRgSize(), rg);

            if (list.isEmpty()) {
                System.out.println("Não encontrado!");
            } else {
                for (RowModel row : list) {
                    System.out.println(row.toString());
                }
            }

        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void searchByNameUsingLinkedList() {

        System.out.print("Informe o Nome: ");
        String name = scanner.next();
        try {
            System.out.println("Buscando registro de Nome: " + name + "...\n");

            LinkedListGenerator generator = new LinkedListGenerator(this.file, this.rm.getRowSize(), this.rm.getNameBeginIndex(), this.rm.getNameSize());
            if (this.linkedListRootNode == null) {
                linkedListRootNode = generator.generate();
            }

            generator.show(linkedListRootNode, name);

        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    private void generateBTree() {
        BTreeGenerator generator = new BTreeGenerator(this.file, this.rm.getRowSize(), this.rm.getRgBeginIndex(), this.rm.getRgSize());
        try {
            this.bTreeRootNode = generator.generate();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void generateAgeHashIndexFile() {
        HashIndexFileGenerator generator = new HashIndexFileGenerator(file, new File("agehashindex.txt"), rm.getRowSize(), rm.getAgeBeginIndex(), rm.getAgeSize());

        try {
            generator.generate();
            hashIndexBlockSize = generator.getBlockSize();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ConsoleMenuView.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
